<template>
  <el-dialog v-model="dialogVisible" class="custom-dialog-class" title="订单详情" top="65px" @opened="resetData">
    <div class="flex">
      <div class="left" :class="{ expend: isExpend }">
        <div id="order-map"></div>
        <div
          class="hamburger-container w-[26px] h-[70px] leading-[70px] absolute right-0 mr-[-1px] top-1/2 translate-y-[-50%] cursor-pointer text-center"
          @click="isExpend = !isExpend"
        >
          <el-icon color="#777C90" size="14px" class="fold-inner" :class="{ 'fold-inner-rotate': isExpend }">
            <ep-ArrowRightBold />
          </el-icon>
        </div>
      </div>
      <div class="right" :class="{ fold: isExpend }">
        <el-scrollbar max-height="600px">
          <div class="pl-8">
            <div class="header pl-6">订单信息</div>
            <el-descriptions :column="2" border>
              <el-descriptions-item label="订单状态" align="center" label-class-name="w-[110px]" class-name="detail-content">
                未完成
              </el-descriptions-item>
              <el-descriptions-item label="卸货方式" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.unloadWay }}
              </el-descriptions-item>

              <el-descriptions-item label="订单编号" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.waybillCode }}
              </el-descriptions-item>
              <el-descriptions-item label="产线" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.productionLine }}
              </el-descriptions-item>

              <el-descriptions-item label="所属站点" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.mixingStationName }}
              </el-descriptions-item>
              <el-descriptions-item label="合同编号" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.contractCode }}
              </el-descriptions-item>

              <el-descriptions-item label="客户名称" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.customerName }}
              </el-descriptions-item>
              <el-descriptions-item label="销售员" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.saleMan }}
              </el-descriptions-item>

              <el-descriptions-item label="工程名称" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.engineeringName }}
              </el-descriptions-item>
              <el-descriptions-item label="联系人" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.contactPerson }}
              </el-descriptions-item>

              <el-descriptions-item label="实际工程名称" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.actualEngineeringName }}
              </el-descriptions-item>
              <el-descriptions-item label="联系人电话" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.contactPhone }}
              </el-descriptions-item>

              <el-descriptions-item label="实际送货地址" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.actualDeliveryAddress }}
              </el-descriptions-item>
              <el-descriptions-item label="预计开盘时间" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.launchTime }}
              </el-descriptions-item>

              <el-descriptions-item label="订货量[方]" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.reserveVolume }}
              </el-descriptions-item>
              <el-descriptions-item label="实际开盘时间" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.actualLaunchTime }}
              </el-descriptions-item>

              <el-descriptions-item label="已送量" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.deliveredVolume }}
              </el-descriptions-item>
              <el-descriptions-item label="订单备注" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.remark }}
              </el-descriptions-item>

              <el-descriptions-item label="施工部位" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.buildPlace }}
              </el-descriptions-item>
              <el-descriptions-item label="在途车辆" align="center" label-class-name="w-[110px]" class-name="detail-content">
                <el-text type="primary">{{ orderDetail?.outBoundCarNum }}</el-text>
              </el-descriptions-item>

              <el-descriptions-item label="强度等级" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.concreteStrengthGrade }}
              </el-descriptions-item>
              <el-descriptions-item label="异常状态" align="center" label-class-name="w-[110px]" class-name="detail-content">
                <el-text v-if="orderDetail?.expStatus === 1" type="primary">正常</el-text>
                <el-text v-if="orderDetail?.expStatus === 2" type="danger">异常</el-text>
              </el-descriptions-item>

              <el-descriptions-item label="特殊要求" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.specialRequirements }}
              </el-descriptions-item>
              <el-descriptions-item label="异常运单" align="center" label-class-name="w-[110px]" class-name="detail-content">
                <template v-if="orderDetail?.expOrderCodeList && orderDetail?.expOrderCodeList.length">
                  <span v-for="(item, index) in orderDetail.expOrderCodeList" :key="item">
                    <el-link type="primary" @click="handleExpWaybillClick(item)">{{ item }}</el-link>
                    <span v-if="index !== orderDetail?.expOrderCodeList.length - 1">、</span>
                  </span>
                </template>
              </el-descriptions-item>

              <el-descriptions-item label="塌落度" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.concreteSlump }}
              </el-descriptions-item>
              <el-descriptions-item label="卸货地址" align="center" label-class-name="w-[110px]" class-name="detail-content">
                {{ orderDetail?.receiveAddress }}
              </el-descriptions-item>
            </el-descriptions>
          </div>
        </el-scrollbar>
      </div>
      <!-- 地图信息弹框样式 -->
      <div class="hidden">
        <InfoBox ref="box" :car-info="carInfo" @close="handleInfoClose" />
      </div>
    </div>
    <div class="bottom relative h-[100px] mt-12 bg-white rounded-lg flex">
      <div class="grow flex">
        <div>
          <div class="text-black h-[50px] pt-[20px] pl-[30px] pr-[10px]">去程车辆</div>
          <div class="text-black h-[50px] leading-[30px] pl-[30px] pr-[10px]">回程车辆</div>
        </div>
        <div class="grow relative">
          <!-- 分割线 -->
          <svg class="svg-line absolute top-[50%] translate-y-[-50%]" width="100%" viewBox="0 0 800 20">
            <path d="M20 18 L 0 10 L 800 10 L 780 2" />
          </svg>

          <!-- 去程 -->
          <div class="flex justify-around items-end h-[50px]">
            <el-tooltip v-for="car in outwardCarList" :key="car.carNumber" placement="top" popper-class="popper">
              <template #content>
                <div>{{ car.carCode + ' - ' + car.carNumber }}</div>
                <div>预计送达：{{ car.arriveTime }}</div>
              </template>
              <template #default>
                <div class="inline cursor-pointer" :style="progressCarStyle(car)">
                  <svg class="mx-[2px] car" :class="{ warning: car.expStatus === 2 }" width="30" height="30" @click="handleCarClick(car)">
                    <use xlink:href="#truck"></use>
                  </svg>
                </div>
              </template>
              <!-- <svg class="mx-[2px] cursor-pointer car" width="30" height="30" @click="handleCarClick(car)">
                <use xlink:href="#truck"></use>
              </svg> -->
            </el-tooltip>
          </div>

          <div class="flex justify-around h-[50px]">
            <el-tooltip v-for="car in returnCarList" :key="car.carNumber" placement="top" popper-class="popper">
              <template #content>
                <div>{{ car.carCode + ' - ' + car.carNumber }}</div>
                <div>预计到达：{{ car.arriveTime }}</div>
              </template>

              <template #default>
                <div class="inline cursor-pointer mt-[2px]" :style="progressCarStyle(car, true)">
                  <svg
                    class="mx-[2px] car reverse"
                    :class="{ warning: car.expStatus === 2 }"
                    width="30"
                    height="30"
                    @click="handleCarClick(car)"
                  >
                    <use xlink:href="#truck"></use>
                  </svg>
                </div>
              </template>
              <!-- <svg class="mx-[2px] cursor-pointer car reverse warning" width="30" height="30" @click="handleCarClick(car)">
                <use xlink:href="#truck"></use>
              </svg> -->
            </el-tooltip>
          </div>
        </div>
      </div>
      <div class="text-black box-content w-[220px] pl-[10px] h-full flex flex-col justify-center">
        <div>平均送达时长：{{ minsToDate(orderDetail?.averageDeliveryMin || 0) }}</div>
        <div>平均卸货时长：{{ minsToDate(orderDetail?.averageUnloadingMin || 0) }}</div>
        <div>平均返程时长：{{ minsToDate(orderDetail?.averageReturnTripMin || 0) }}</div>
      </div>
    </div>
  </el-dialog>

  <WaybillDetail :id="expWaybillId" v-model:visible="expDialogVisible" :waybill-code="expWaybillCode" />
</template>

<script lang="ts" setup>
import moment from 'moment'

import type { CarInfoData } from '@/api/vehicle-monitor/vehicleMonitor'

import { getCarInfo } from '@/api/vehicle-monitor/vehicleMonitor'

import { getWaybillRail } from '@/api/waybill/index'
import { RailData, LoadType } from '@/api/waybill/index'

import { getOrderDetailData, getOutBoundCarData } from '@/api/order/index'
import type { OrderDetail, Vehicle, SendVehicle, ReturnVehicle } from '@/api/order/index'

import { useMap } from '@/hooks/useMap/index'
import { wgs84ToGCJ02 } from '@/utils/mapUtil.ts'
import { minsToDate } from '@/utils/date'

import InfoBox from '@/views/vehicle-monitor/components/CarInfoWindow.vue'
import WaybillDetail from '@/views/waybill/detail.vue'

import { createMarker, initRailType, createRails } from '@/views/waybill/map'

interface Props {
  id: string
  visible: boolean
}

const props = defineProps<Props>()

const emits = defineEmits(['update:visible'])

const dialogVisible = computed({
  get() {
    return props.visible
  },
  set(val) {
    emits('update:visible', val)
  }
})

const isExpend = ref(false)

const box = ref()

const { map, initMap, AMap } = useMap('order-map', {
  manual: true
})

let windowInstance = null
// 获取实例
const getInfoBox = (el?: HTMLElement) => {
  if (windowInstance) return windowInstance
  //信息窗体的内容
  windowInstance = new AMap.value.InfoWindow({
    isCustom: true, //使用自定义窗体
    autoMove: false,
    content: el,
    offset: new AMap.value.Pixel(0, -25)
  })

  return windowInstance
}

const carInfo = reactive<CarInfoData>({})
const openInfoBox = (map, position) => {
  const el = box.value.$el
  const infoWindow = getInfoBox(el)
  infoWindow.open(map, position)
}

const handleInfoClose = () => {
  const infoWindow = getInfoBox()
  infoWindow.close()
}

const setMapCenter = (map, center?: any) => {
  center = center || [116.438064, 40.024995]
  map.setCenter(center)
  map.setZoom(8)
}

const orderDetail = ref<OrderDetail>(null) // 订单详情

const outwardCarList = ref<SendVehicle[]>([]) // 去程车辆

const returnCarList = ref<ReturnVehicle[]>([]) // 返程车辆列表

const resetData = async () => {
  isExpend.value = false
  // onMounted，dialog 内部懒加载
  // 地图初始化失败
  // 需要手动调用
  if (!map.value) await initMap()
  // 初始化地图中心位置
  setMapCenter(map.value)
  await getDetail()
  drawMap()
}

const expDialogVisible = ref(false)
const expWaybillId = ref('')
const expWaybillCode = ref('')
// 点击车辆，异常打开运单弹框
const handleCarClick = (car: Vehicle) => {
  // 异常运单
  if (car.expStatus === 2) {
    expWaybillId.value = car.id
    expDialogVisible.value = true
  }
}

const handleExpWaybillClick = (code: string) => {
  expWaybillId.value = ''
  expWaybillCode.value = code
  expDialogVisible.value = true
}
// 获取订单详情
async function getDetail() {
  const { result } = await getOrderDetailData({ id: props.id })
  if (typeof result.expOrderCodeList === 'string') {
    result.expOrderCodeList = result.expOrderCodeList.split(',')
  }
  orderDetail.value = result
  const { outBoundCarList, returnCarList: returnCars } = result
  if (outBoundCarList) {
    outwardCarList.value = formatSendCar(outBoundCarList, result.averageDeliveryMin)
  }
  if (returnCars) {
    returnCarList.value = formatReturnCar(returnCars, result.averageReturnTripMin)
  }
}

function drawMap() {
  getMapCarData()
  getRailData(orderDetail.value.waybillCode)
}

async function getMapCarData() {
  // 去程车辆数据
  const { result } = await getOutBoundCarData({ waybillCode: orderDetail.value.waybillCode })
  if (result.length) {
    result.forEach(truck => {
      truck.content = `<svg width="32" height="32" fill="${truck.orderStatus !== 0 ? '#3a75ff' : '#ffbf00'}">
        <use xlink:href="#truck"></use>
      </svg>`
      const marker = createMarker(AMap.value, truck)
      marker.on('click', handleMapCarClick)
      marker.setExtData(truck)
      map.value.add(marker)
    })
    map.value.setFitView()
  }
}

// 获取围栏数据
async function getRailData(wayBillCode: string) {
  const { result } = await getWaybillRail({ oddCode: wayBillCode, oddType: 2 })
  const temp: RailData[] = []
  // 搅拌站围栏，即上货围栏
  if (result.mixingStationRails && result.mixingStationRails.length) temp.push(...initRailType(result.mixingStationRails, LoadType.Load))
  // 客户围栏，即卸货围栏
  if (result.customerRails && result.customerRails.length) temp.push(...initRailType(result.customerRails, LoadType.Unload))

  if (temp.length) {
    const rails = createRails(AMap.value, temp)
    map.value.add(rails)
    map.value.setFitView()
    return rails
  }
  return []
}

const handleMapCarClick = ev => {
  const target = ev.target
  const data = target.getExtData()
  const param = { deviceId: data.deviceId, carNumber: data.carNumber, mixingStationNumber: orderDetail.value.mixingStationCode }

  getCarInfo(param).then(async ({ result }) => {
    Object.assign(carInfo, result)
    openInfoBox(map.value, wgs84ToGCJ02(data.lng, data.lat))
  })
}

/**
 * 计算车辆运输进度
 * @param carList 车辆信息
 * @param estimate 预估运输时长，可能没有
 */
function formatSendCar(carList: SendVehicle[], estimate?: string): Required<SendVehicle>[] {
  const estimateToNumber = +estimate
  return carList.map(car => {
    const { leaveTime } = car
    let progress = -1
    if (estimateToNumber) {
      const usedTime = moment().diff(moment(leaveTime))
      const usedTimeToMins = usedTime / 1000 / 60
      progress = usedTimeToMins >= estimateToNumber ? 100 : Math.floor((usedTimeToMins / estimateToNumber) * 100)
    }

    return {
      ...car,
      arriveTime: estimateToNumber ? moment(leaveTime).add(estimateToNumber, 'm').format('YYYY-MM-DD HH:mm:ss') : '-',
      progress
    }
  })
}

/**
 * 计算车辆运输进度
 * @param carList 车辆信息
 * @param estimate 预估运输时长，可能没有
 */
function formatReturnCar(carList: ReturnVehicle[], estimate?: string): Required<ReturnVehicle>[] {
  const estimateToNumber = +estimate
  return carList.map(car => {
    // 返程存在有预估到达时长，但是车辆还没开始返程情况
    // 也就是 unloadEndTime 不存在
    const { unloadEndTime } = car
    let progress = -1
    if (estimateToNumber) {
      // 没有 unloadEndTime，还未开始返程，进度 0
      const usedTime = unloadEndTime ? moment().diff(moment(unloadEndTime)) : 0
      const usedTimeToMins = usedTime / 1000 / 60
      progress = usedTimeToMins >= estimateToNumber ? 100 : Math.floor((usedTimeToMins / estimateToNumber) * 100)
    }

    return {
      ...car,
      arriveTime: estimateToNumber ? moment(unloadEndTime).add(estimateToNumber, 'm').format('YYYY-MM-DD HH:mm:ss') : '-',
      progress
    }
  })
}

function progressCarStyle(car: SendVehicle | ReturnVehicle, isReverse = false) {
  if (car.progress < 0) return ''
  return `position:absolute;${isReverse ? 'right' : 'left'}: ${car.progress}%;transform: translateX(${isReverse ? '100' : '-100'}%);`
}
</script>
<style>
@media only screen and (min-width: 1600px) {
  .custom-dialog-class {
    --el-dialog-width: 80%;
  }
}

@media only screen and (max-width: 1600px) {
  .custom-dialog-class {
    --el-dialog-width: 1280px;
  }
}
</style>

<style lang="scss" scoped>
.left {
  width: 50%;
  position: relative;
  transition: width 0.28s;
  &.expend {
    width: 100%;
  }
  #order-map {
    height: 600px;
  }
}

.right {
  width: 50%;
  position: relative;
  transition: width 0.28s;
  max-height: 600px;
  &.fold {
    width: 0;
  }
  .header {
    font-weight: 600;
    line-height: 50px;
  }
}

.hamburger-container {
  background: url(@/assets/images/hamburger-bg-right.png) no-repeat;
  background-size: 100% 100%;
  .fold-inner {
    transform: rotate(180deg);
    transition: transform 0.25s ease-in;
    &-rotate {
      transform: rotate(0);
      transition: transform 0.25s ease-out;
    }
  }
}
.bottom {
  border-radius: 8px;
  box-shadow: -2px -2px 4px #00000059;
}
.svg-line {
  fill: none;
  stroke: #409eff;
  stroke-linecap: round;
  stroke-linejoin: miter;
  stroke-width: 2;
}

.car {
  fill: var(--el-color-primary);
}

.reverse {
  transform: rotateY(180deg);
}
.warning {
  fill: var(--el-color-danger-dark-2);
}

.idle {
  fill: var(--el-color-warning);
}

:deep(.detail-content) {
  width: calc((100% - 220px) / 2);
}

@media only screen and (min-width: 1600px) {
  .custom-dialog-class {
    --el-dialog-width: 80%;
  }
}

@media only screen and (max-width: 1600px) {
  .custom-dialog-class {
    --el-dialog-width: 1280px;
  }
}
</style>
